#include <winsock2.h>
#include "MySQL/mysql.h"
#include "CDb.h"
#include "CConsole.h"
#include "CChar.h"
#include "CLinkshell.h"

#include "CitemContainer.h"

CItemContainer::CItemContainer(unsigned char locationID, CChar * owner) {
	m_itemList = NULL;
	m_size = 0;

	setId(locationID);
	setOwner(owner);
}

CItemContainer::~CItemContainer() {
	for(unsigned char i = 0; i < m_size; i++) {
		if(m_itemList[i] != NULL)
			delete m_itemList[i];
	}
	if(m_itemList != NULL) {
		delete [] m_itemList;
	}
}

unsigned char CItemContainer::getId() {
	return m_id;
}

void CItemContainer::setId(unsigned char id) {
	m_id = id;
}


unsigned char CItemContainer::getSize() {
	return m_size;
}

void CItemContainer::setSize(unsigned char size) {
	if(size == 0)
		return;
	if(size <= m_size) 
	{
		CConsole::outDebOnly("Size is smaller or equal to current container size.");
		return;
	}
	// Create temporary new list of new bigger size
	CItem ** newList;
	newList = new CItem*[size];
	memset( newList, 0, size * sizeof(CItem*) );

	if(m_itemList != NULL) {
		// Copy the items onto the new list
		memcpy( newList, m_itemList, m_size * sizeof(CItem*) );

		// Delete old list from memory
		memset( m_itemList, 0, m_size * sizeof(CItem*) );
		delete [] m_itemList;
	}

	// Set itemList to new bigger list
	m_itemList = newList;
	m_size = size;
}

CItem * CItemContainer::createItem(unsigned short itemID) {
	if( (itemID >= 0x0200) && (itemID <= 0x0206) ) {
		CLinkshellItem * item = new CLinkshellItem(itemID);
		return item;
	}

	if( (itemID >= 0x0000) && (itemID <= 0x0FFF) ) {
		CGeneralItem * item = new CGeneralItem(itemID);
		return item;
	}

	if( (itemID >= 0x1000) && (itemID <= 0x1FFF) ) {
		CUsableItem * item = new CUsableItem(itemID);
		return item;
	}

	if( (itemID >= 0x2000) && (itemID <= 0x2BFF) ) {
		CPuppetItem * item = new CPuppetItem(itemID);
		return item;
	}

	if( (itemID >= 0x2C00) && (itemID <= 0x3FFF) ) {
		CArmorItem * item = new CArmorItem(itemID);
		return item;
	}

	if( (itemID >= 0x4000) && (itemID <= 0x6FFF) ) {
		CWeaponItem * item = new CWeaponItem(itemID);
		return item;
	}

	return NULL;
}

unsigned char CItemContainer::addItem(unsigned short itemID, unsigned long quantity) {
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return 0;
	}
	CItem * item;
	item = createItem(itemID);
	if (item == NULL) {
		CConsole::outDebOnly("null pointer for item.");
		return 0;
	}
	if(item->getType() == ITEM_LINKSHELL)
		((CLinkshellItem*)item)->setLinkshellId(quantity);
	else {
		if(quantity > item->getStackSize())
			quantity = item->getStackSize();
		item->setQuantity(quantity);
	}
	
	for(unsigned char slotID = 1; slotID <= m_size; slotID++) {
		if(m_itemList[slotID-1] == NULL) {
			m_itemList[slotID-1] = item;
			CConsole::outDebOnly("Adding quantity %i of item %i into slot %d.",quantity, itemID, slotID);
			return slotID;
		}
	}
	CConsole::outDebOnly("Container full.");
	return 0xFF;
}

unsigned char CItemContainer::moveItemTo(CItem * item) {
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return 0;
	}
	for(unsigned char slotID = 1; slotID <= m_size; slotID++) {
		if(m_itemList[slotID-1] == NULL) {
			m_itemList[slotID-1] = item;
			CConsole::outDebOnly("Adding item into slot %d.",slotID);
			return slotID;
		}
	}
	CConsole::outDebOnly("Container full.");
	return 0xFF;
}

void CItemContainer::updateItem(unsigned char slotID, CItem * item) {
	if(slotID <= getSize())
		m_itemList[slotID-1] = item;
}

void CItemContainer::removeItem(unsigned char slotID) {
	if(m_itemList[slotID-1] != NULL) {
		delete m_itemList[slotID-1];
		m_itemList[slotID-1] = NULL;
	}
}

void CItemContainer::removeQuantity(unsigned char slotID, unsigned long quantity) {
	if(quantity == 0) {
		CConsole::outDebOnly("Trying to remove quantity 0.");
		return;
	}
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return;
	}
	if(slotID <= getSize()) {
		CItem * item;
		item = getItem(slotID);
		if(item != NULL) {
			unsigned long itemQty = item->getQuantity();
			if(itemQty > quantity)
				item->setQuantity(itemQty - quantity);
			else if(itemQty == quantity) {
				unsigned long lsID = 0;
				if(item->getId() == 0x201)
					lsID = ((CLinkshellItem*)item)->getLinkshellId();
				removeItem(slotID);
				if(lsID > 0)
					CLinkshell::breakLinkshell(lsID);
			} else
				CConsole::outDebOnly("Container slot does not have sufficient quantity.");
		} else
			CConsole::outDebOnly("Item null.");
	}
}

CItem * CItemContainer::getItem(unsigned char slotID) {
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return NULL;
	}
	if( (slotID > getSize()) || (slotID == 0) )
		return NULL;

	return m_itemList[slotID-1];
}

void CItemContainer::setItem(unsigned char slotID, CItem * item) {
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return;
	}
	if( (slotID > getSize()) || (slotID == 0) )
		return;

	m_itemList[slotID-1] = item;
}


unsigned long CItemContainer::getQuantity(unsigned char slotID) {
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return 0;
	}
	CItem * item;
	item = getItem(slotID);
	if(item != NULL)
		return item->getQuantity();
	else
		return 0;
}

unsigned char CItemContainer::getType(unsigned char slotID) {
	if(getSize() == 0) {
		CConsole::outDebOnly("Container size 0");
		return 0;
	}
	CItem * item;
	item = getItem(slotID);
	if(item != NULL)
		return item->getType();
	else
		return 0;
}

unsigned long CItemContainer::getItemQuantity(unsigned short itemID) {
	if(itemID == 0)
		return 0;
	unsigned long quantity = 0;
	for(unsigned char slotID = 1; slotID <= getSize(); slotID++) {
		CItem * item;
		item = getItem(slotID);
		if(item != NULL)
			if(item->getId() == itemID)
				quantity += item->getQuantity();
	}
	return quantity;
}

void CItemContainer::loadSQL(unsigned char containerID) {
	MYSQL_RES * res;
	MYSQL_ROW row;
	char query[8192];
	CChar * owner;
	owner = getOwner();
	if(owner == NULL)
		return;
	setId(containerID);

	sprintf(query, "SELECT item, quantity, addInfoFlag, addInfoKey, id FROM char_inventory WHERE charid = %i AND location = %i ORDER BY id ASC",owner->getId(),containerID);
	int count = (int)strlen(query);

	MYSQL* mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);

	res = mysql_store_result(mysqlConn);
	CDb::pushConn(mysqlConn); //release conn

	if(!res) {
		CConsole::outErr("Error looking up character inventory");
		return;
	}
	if(!mysql_num_rows(res)){
		mysql_free_result(res);
	} else {
		while((row = mysql_fetch_row(res)))
		{
			CItem * item = this->createItem(atoi(row[0]));
			if (item != NULL) {
				item->setQuantity(atoi(row[1]));
				unsigned short addInfoFlag = atoi(row[2]);
				if(addInfoFlag == 1) {
					((CLinkshellItem*)item)->setLinkshellId(atoi(row[3]));
				}
				unsigned char slotID = atoi(row[4]);
				updateItem(slotID, item);
			}
		}
		mysql_free_result(res);
	}
}

void CItemContainer::updateSQL(unsigned char slotID) {
	char query[8192];
	CChar * owner;
	owner = getOwner();
	if(owner == NULL)
		return;

	unsigned char locationID = this->getId();

	sprintf(query, "DELETE FROM char_inventory WHERE charid = %i AND location = %i AND id = %i", owner->getId(), locationID, slotID);
	int count = (int)strlen(query);

	MYSQL* mysqlConn=CDb::getConn(); //get conn
	mysql_real_query(mysqlConn, query, count);
	CDb::pushConn(mysqlConn); //release conn

	CItem * item;
	item = getItem(slotID);
	if(item == NULL)
		return;
	if(item->getQuantity() == 0)
		return;

	unsigned long quantity = item->getQuantity();
	unsigned short itemID = item->getId();
	unsigned short addInfoFlag = 0;
	unsigned long addInfoKey = 0;
	if(item->getType() == ITEM_LINKSHELL) {
		addInfoFlag = 1;
		addInfoKey = ((CLinkshellItem*)item)->getLinkshellId();
	}

	if(item->getId() != 515) {
		sprintf(query, "INSERT INTO char_inventory (`charid`, `quantity`, `item`, `id`, `location`, `addInfoFlag`, `addInfoKey`) values(%i, %i, %i, %i, %i, %i, %i)", owner->getId(), quantity, itemID, slotID, locationID, addInfoFlag, addInfoKey);
		count = (int)strlen(query);

		mysqlConn=CDb::getConn(); //get conn
		mysql_real_query(mysqlConn, query, count);
		CDb::pushConn(mysqlConn); //release conn
	}

}

void CItemContainer::setOwner(CChar * owner) {
	m_pOwner = owner;
}

CChar * CItemContainer::getOwner() {
	return m_pOwner;
}

